﻿using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using GeoFramework;
using Microsoft.SqlServer.Types;
using VO.Entities;

namespace VO.Business.Utils
{
    public class GeoUtils
    {
        public static string SerializeTrack(List<LocationPoint> locationPoints)
        {
            if (locationPoints.Count > 0)
            {
                SqlGeographyBuilder geoBuilder = new SqlGeographyBuilder();
                geoBuilder.SetSrid(4326);
                geoBuilder.BeginGeography(OpenGisGeographyType.LineString);
                int counter = 0;
                foreach (LocationPoint point in locationPoints)
                {
                    if (counter == 0)
                    {
                        geoBuilder.BeginFigure(point.Latitude, point.Longitude);
                    }
                    else
                    {
                        geoBuilder.AddLine(point.Latitude, point.Longitude);
                    }
                    counter++;
                }
                geoBuilder.EndFigure();
                geoBuilder.EndGeography();
                return geoBuilder.ConstructedGeography.ToString();
            }
            return string.Empty;
        }

        public static List<LocationPoint> DeserializeTrack(string strTrack)
        {
            List<LocationPoint> list = new List<LocationPoint>();

            if (string.IsNullOrEmpty(strTrack))
                return list;
            
            SqlGeography s1 = SqlGeography.STLineFromText(new SqlChars(strTrack.ToCharArray()), 4326);
            SqlInt32 nopoints = s1.STNumPoints();
            for (int i = 1; i <= nopoints; i++)
            {
                SqlGeography point = s1.STPointN(i);
                list.Add(new LocationPoint((double)point.Lat, (double)point.Long));
            }
            return list;
        }

        public static int GetTrackLength(Track track)
        {
            List<LocationPoint> locationPoints = GeoUtils.DeserializeTrack(track.GeoString);
            //TODO - store track length in DB for better perf
            double trackLength = 0;
            if (locationPoints.Count > 1)
            {
                for (int i = 0; i < locationPoints.Count - 1; i++)
                {
                    LocationPoint pointStart = locationPoints[i];
                    LocationPoint pointEnd = locationPoints[i + 1];
                    Segment seg = new Segment(new Position(new Latitude(pointStart.Latitude), new Longitude(pointStart.Longitude)),
                        new Position(new Latitude(pointEnd.Latitude), new Longitude(pointEnd.Longitude)));
                    double distance = seg.Distance.ToMeters().Value / 1000;
                    trackLength += distance;
                }
            }
            return (int)trackLength;
        }
    }
}
